package com.zg.datapush.engine;

import cn.hutool.core.util.StrUtil;
import com.zg.datapush.constant.DataPushConstants;
import com.zg.common.core.dao.datapush.entity.DpFieldMapping;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据转换引擎
 * @author zg
 */
@Component
@Slf4j
public class DataTransformEngine {

    /**
     * 转换数据
     */
    public List<Map<String, Object>> transformData(List<Map<String, Object>> sourceData,
                                                   List<DpFieldMapping> fieldMappings) {
        List<Map<String, Object>> result = new ArrayList<>();

        for (Map<String, Object> sourceRecord : sourceData) {
            result.add(transformSingleRecord(sourceRecord, fieldMappings));
        }

        return result;
    }

    /**
     * 转换单条数据
     */
    public Map<String, Object> transformSingleRecord(Map<String, Object> sourceRecord,
                                                     List<DpFieldMapping> fieldMappings) {
        Map<String, Object> targetRecord = new HashMap<>();

        for (DpFieldMapping mapping : fieldMappings) {
            Object sourceValue = sourceRecord.get(mapping.getSourceField());
            Object targetValue = transformValue(sourceValue, mapping);
            targetRecord.put(mapping.getTargetField(), targetValue);
        }

        return targetRecord;
    }

    /**
     * 转换单个字段值
     */
    private Object transformValue(Object sourceValue, DpFieldMapping mapping) {
        if (sourceValue == null) {
            return null;
        }

        // 如果有转换表达式，执行转换
        if (StrUtil.isNotBlank(mapping.getConvertExpression())) {
            return executeConvertExpression(sourceValue, mapping.getConvertExpression());
        }

        // 否则直接返回原值
        return sourceValue;
    }

    /**
     * 执行转换表达式
     */
    private Object executeConvertExpression(Object sourceValue, String expression) {
        try {
            String strValue = sourceValue.toString();

            // 类型转换
            if (DataPushConstants.CONVERT_TO_STRING.equals(expression)) {
                return strValue;
            } else if (DataPushConstants.CONVERT_TO_INT.equals(expression)) {
                return Integer.valueOf(strValue);
            } else if (DataPushConstants.CONVERT_TO_LONG.equals(expression)) {
                return Long.valueOf(strValue);
            } else if (DataPushConstants.CONVERT_TO_DOUBLE.equals(expression)) {
                return Double.valueOf(strValue);
            } else if (DataPushConstants.CONVERT_TO_FLOAT.equals(expression)) {
                return Float.valueOf(strValue);
            } else if (DataPushConstants.CONVERT_TO_BOOLEAN.equals(expression)) {
                return Boolean.valueOf(strValue);
            }

            // 字符串操作
            else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_CONCAT)) {
                String suffix = expression.substring(DataPushConstants.CONVERT_PREFIX_CONCAT.length());
                return strValue + suffix;
            } else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_PREFIX)) {
                String prefix = expression.substring(DataPushConstants.CONVERT_PREFIX_PREFIX.length());
                return prefix + strValue;
            } else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_SUBSTRING)) {
                String[] params = expression.substring(DataPushConstants.CONVERT_PREFIX_SUBSTRING.length()).split(",");
                int start = Integer.parseInt(params[0]);
                if (params.length > 1) {
                    int end = Integer.parseInt(params[1]);
                    return strValue.substring(start, Math.min(end, strValue.length()));
                } else {
                    return strValue.substring(start);
                }
            } else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_REPLACE)) {
                String[] params = expression.substring(DataPushConstants.CONVERT_PREFIX_REPLACE.length()).split(",", 2);
                if (params.length == 2) {
                    return strValue.replace(params[0], params[1]);
                }
            } else if (DataPushConstants.CONVERT_TO_UPPER_CASE.equals(expression)) {
                return strValue.toUpperCase();
            } else if (DataPushConstants.CONVERT_TO_LOWER_CASE.equals(expression)) {
                return strValue.toLowerCase();
            } else if (DataPushConstants.CONVERT_TRIM.equals(expression)) {
                return strValue.trim();
            }

            // 数值操作
            else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_ADD)) {
                double addValue = Double.parseDouble(expression.substring(DataPushConstants.CONVERT_PREFIX_ADD.length()));
                double originalValue = Double.parseDouble(strValue);
                return originalValue + addValue;
            } else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_MULTIPLY)) {
                double multiplyValue = Double.parseDouble(expression.substring(DataPushConstants.CONVERT_PREFIX_MULTIPLY.length()));
                double originalValue = Double.parseDouble(strValue);
                return originalValue * multiplyValue;
            }

            // 日期格式化
            else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_DATE_FORMAT)) {
                String format = expression.substring(DataPushConstants.CONVERT_PREFIX_DATE_FORMAT.length());
                return formatDate(sourceValue, format);
            }

            // 当前时间戳
            else if (DataPushConstants.CONVERT_CURRENT_TIMESTAMP.equals(expression)) {
                return System.currentTimeMillis();
            } else if (DataPushConstants.CONVERT_CURRENT_DATE.equals(expression)) {
                return new Date();
            } else if (expression.startsWith(DataPushConstants.CONVERT_PREFIX_CURRENT_DATE_FORMAT)) {
                String format = expression.substring(DataPushConstants.CONVERT_PREFIX_CURRENT_DATE_FORMAT.length());
                return formatCurrentDate(format);
            }

            // 默认返回原值
            return sourceValue;

        } catch (Exception e) {
            log.warn("转换表达式执行失败: {}, 原值: {}", expression, sourceValue, e);
            return sourceValue;
        }
    }

    /**
     * 格式化日期
     */
    private Object formatDate(Object dateValue, String format) {
        try {
            if (dateValue == null) {
                return null;
            }

            Date date = null;

            // 处理不同类型的日期输入
            if (dateValue instanceof Date) {
                date = (Date) dateValue;
            } else if (dateValue instanceof Timestamp) {
                date = new Date(((Timestamp) dateValue).getTime());
            } else if (dateValue instanceof Long) {
                date = new Date((Long) dateValue);
            } else if (dateValue instanceof String) {
                // 尝试解析字符串日期
                String dateStr = (String) dateValue;
                try {
                    // 尝试解析时间戳
                    long timestamp = Long.parseLong(dateStr);
                    date = new Date(timestamp);
                } catch (NumberFormatException e) {
                    // 尝试解析常见日期格式
                    date = parseStringDate(dateStr);
                }
            }

            if (date != null) {
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                return sdf.format(date);
            }

            return dateValue;

        } catch (Exception e) {
            log.warn("日期格式化失败: {}, 格式: {}", dateValue, format, e);
            return dateValue;
        }
    }

    /**
     * 解析字符串日期
     */
    private Date parseStringDate(String dateStr) {
        String[] patterns = {
            "yyyy-MM-dd HH:mm:ss",
            "yyyy-MM-dd",
            "yyyy/MM/dd HH:mm:ss",
            "yyyy/MM/dd",
            "dd/MM/yyyy",
            "MM/dd/yyyy",
            "yyyy-MM-dd'T'HH:mm:ss",
            "yyyy-MM-dd'T'HH:mm:ss.SSS"
        };

        for (String pattern : patterns) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                // 继续尝试下一个格式
            }
        }

        throw new IllegalArgumentException("无法解析日期字符串: " + dateStr);
    }

    /**
     * 格式化当前日期
     */
    private String formatCurrentDate(String format) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(new Date());
        } catch (Exception e) {
            log.warn("格式化当前日期失败: {}", format, e);
            return new Date().toString();
        }
    }
}
